﻿Imports System
Imports System.CodeDom
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Reflection
Imports System.Text
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities.Rules
    Friend Class ObjectCreateExpression
        Inherits RuleExpressionInternal
        ' Methods
        Friend Overrides Sub AnalyzeUsage(ByVal expression As CodeExpression, ByVal analysis As RuleAnalysis, ByVal isRead As Boolean, ByVal isWritten As Boolean, ByVal qualifier As RulePathQualifier)
            Dim expression2 As CodeObjectCreateExpression = DirectCast(expression, CodeObjectCreateExpression)
            Dim expression3 As CodeExpression
            For Each expression3 In expression2.Parameters
                RuleExpressionWalker.AnalyzeUsage(analysis, expression3, True, False, Nothing)
            Next
        End Sub

        Friend Overrides Function Clone(ByVal expression As CodeExpression) As CodeExpression
            Dim expression2 As CodeObjectCreateExpression = DirectCast(expression, CodeObjectCreateExpression)
            Dim expression3 As New CodeObjectCreateExpression { _
                .CreateType = TypeReferenceExpression.CloneType(expression2.CreateType) _
            }
            Dim expression4 As CodeExpression
            For Each expression4 In expression2.Parameters
                expression3.Parameters.Add(RuleExpressionWalker.Clone(expression4))
            Next
            Return expression3
        End Function

        Friend Overrides Sub Decompile(ByVal expression As CodeExpression, ByVal stringBuilder As StringBuilder, ByVal parentExpression As CodeExpression)
            Dim childExpr As CodeObjectCreateExpression = DirectCast(expression, CodeObjectCreateExpression)
            Dim flag As Boolean = RuleDecompiler.MustParenthesize(childExpr, parentExpression)
            If flag Then
                stringBuilder.Append("(")
            End If
            stringBuilder.Append("new ")
            RuleDecompiler.DecompileType(stringBuilder, childExpr.CreateType)
            stringBuilder.Append("("c)
            Dim i As Integer
            For i = 0 To childExpr.Parameters.Count - 1
                Dim expression3 As CodeExpression = childExpr.Parameters.Item(i)
                If (expression3 Is Nothing) Then
                    Dim exception As New RuleEvaluationException(String.Format(CultureInfo.CurrentCulture, Messages.NullConstructorTypeParameter, New Object() { i.ToString(CultureInfo.CurrentCulture), childExpr.CreateType }))
                    exception.Data.Item("ErrorObject") = childExpr
                    Throw exception
                End If
                If (i > 0) Then
                    stringBuilder.Append(", ")
                End If
                RuleExpressionWalker.Decompile(stringBuilder, expression3, Nothing)
            Next i
            stringBuilder.Append(")"c)
            If flag Then
                stringBuilder.Append(")")
            End If
        End Sub

        Friend Overrides Function Evaluate(ByVal expression As CodeExpression, ByVal execution As RuleExecution) As RuleExpressionResult
            Dim obj2 As Object
            Dim expression2 As CodeObjectCreateExpression = DirectCast(expression, CodeObjectCreateExpression)
            If (expression2.CreateType Is Nothing) Then
                Dim exception As New RuleEvaluationException(Messages.NullTypeType)
                exception.Data.Item("ErrorObject") = expression2
                Throw exception
            End If
            Dim info As RuleExpressionInfo = execution.Validation.ExpressionInfo(expression2)
            If (info Is Nothing) Then
                Dim exception2 As New InvalidOperationException(Messages.ExpressionNotValidated)
                exception2.Data.Item("ErrorObject") = expression2
                Throw exception2
            End If
            Dim info2 As RuleConstructorExpressionInfo = [TryCast](info,RuleConstructorExpressionInfo)
            If (info2 Is Nothing) Then
                Return New RuleLiteralResult(Activator.CreateInstance(info.ExpressionType))
            End If
            Dim constructorInfo As ConstructorInfo = info2.ConstructorInfo
            Dim parameters As Object() = Nothing
            Dim resultArray As RuleExpressionResult() = Nothing
            If ((Not expression2.Parameters Is Nothing) AndAlso (expression2.Parameters.Count > 0)) Then
                Dim count As Integer = expression2.Parameters.Count
                Dim infoArray As ParameterInfo() = constructorInfo.GetParameters
                parameters = New Object(infoArray.Length  - 1) {}
                Dim length As Integer = infoArray.Length
                If info2.NeedsParamsExpansion Then
                    length -= 1
                End If
                Dim index As Integer = 0
                Do While (index < length)
                    Dim expressionType As Type = execution.Validation.ExpressionInfo(expression2.Parameters.Item(index)).ExpressionType
                    Dim result As RuleExpressionResult = RuleExpressionWalker.Evaluate(execution, expression2.Parameters.Item(index))
                    Dim expression3 As CodeDirectionExpression = [TryCast](expression2.Parameters.Item(index),CodeDirectionExpression)
                    If ((Not expression3 Is Nothing) AndAlso ((expression3.Direction = FieldDirection.Ref) OrElse (expression3.Direction = FieldDirection.Out))) Then
                        If (resultArray Is Nothing) Then
                            resultArray = New RuleExpressionResult(count  - 1) {}
                        End If
                        resultArray(index) = result
                    End If
                    parameters(index) = Executor.AdjustType(expressionType, result.Value, infoArray(index).ParameterType)
                    index += 1
                Loop
                If (length < count) Then
                    Dim info4 As ParameterInfo = infoArray(length)
                    Dim elementType As Type = info4.ParameterType.GetElementType
                    Dim array As Array = Array.CreateInstance(elementType, CInt((count - index)))
                    Do While (index < count)
                        Dim operandType As Type = execution.Validation.ExpressionInfo(expression2.Parameters.Item(index)).ExpressionType
                        Dim result2 As RuleExpressionResult = RuleExpressionWalker.Evaluate(execution, expression2.Parameters.Item(index))
                        array.SetValue(Executor.AdjustType(operandType, result2.Value, elementType), CInt((index - length)))
                        index += 1
                    Loop
                    parameters(length) = array
                End If
            End If
            Try 
                obj2 = constructorInfo.Invoke(parameters)
            Catch exception3 As TargetInvocationException
                If (exception3.InnerException Is Nothing) Then
                    Throw
                End If
                Throw New TargetInvocationException(String.Format(CultureInfo.CurrentCulture, Messages.Error_ConstructorInvoke, New Object() { RuleDecompiler.DecompileType(info2.ExpressionType), exception3.InnerException.Message }), exception3.InnerException)
            End Try
            If (Not resultArray Is Nothing) Then
                Dim i As Integer
                For i = 0 To expression2.Parameters.Count - 1
                    If (Not resultArray(i) Is Nothing) Then
                        resultArray(i).Value = parameters(i)
                    End If
                Next i
            End If
            Return New RuleLiteralResult(obj2)
        End Function

        Friend Overrides Function Match(ByVal expression As CodeExpression, ByVal comperand As CodeExpression) As Boolean
            Dim expression2 As CodeObjectCreateExpression = DirectCast(expression, CodeObjectCreateExpression)
            Dim expression3 As CodeObjectCreateExpression = [TryCast](comperand,CodeObjectCreateExpression)
            If (expression3 Is Nothing) Then
                Return False
            End If
            If Not TypeReferenceExpression.MatchType(expression2.CreateType, expression3.CreateType) Then
                Return False
            End If
            If (expression2.Parameters.Count <> expression3.Parameters.Count) Then
                Return False
            End If
            Dim i As Integer
            For i = 0 To expression2.Parameters.Count - 1
                If Not RuleExpressionWalker.Match(expression2.Parameters.Item(i), expression3.Parameters.Item(i)) Then
                    Return False
                End If
            Next i
            Return True
        End Function

        Friend Overrides Function Validate(ByVal expression As CodeExpression, ByVal validation As RuleValidation, ByVal isWritten As Boolean) As RuleExpressionInfo
            Dim error As ValidationError
            Dim newParent As CodeObjectCreateExpression = DirectCast(expression, CodeObjectCreateExpression)
            If isWritten Then
                [error] = New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.CannotWriteToExpression, New Object() { GetType(CodeObjectCreateExpression).ToString }), &H17A)
                [error].UserData.Item("ErrorObject") = newParent
                validation.Errors.Add([error])
                Return Nothing
            End If
            If (newParent.CreateType Is Nothing) Then
                [error] = New ValidationError(Messages.NullTypeType, &H53D)
                [error].UserData.Item("ErrorObject") = newParent
                validation.Errors.Add([error])
                Return Nothing
            End If
            Dim type As Type = validation.ResolveType(newParent.CreateType)
            If (type Is Nothing) Then
                Return Nothing
            End If
            Dim argumentExprs As New List([Of] CodeExpression)
            Try 
                If Not validation.PushParentExpression(newParent) Then
                    Return Nothing
                End If
                Dim flag As Boolean = False
                Dim i As Integer
                For i = 0 To newParent.Parameters.Count - 1
                    Dim expression3 As CodeExpression = newParent.Parameters.Item(i)
                    If (expression3 Is Nothing) Then
                        [error] = New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.NullConstructorParameter, New Object() { i.ToString(CultureInfo.CurrentCulture), RuleDecompiler.DecompileType(type) }), &H53D)
                        [error].UserData.Item("ErrorObject") = newParent
                        validation.Errors.Add([error])
                        flag = True
                    Else
                        If (RuleExpressionWalker.Validate(validation, expression3, False) Is Nothing) Then
                            flag = True
                        End If
                        argumentExprs.Add(expression3)
                    End If
                Next i
                If flag Then
                    Return Nothing
                End If
            Finally
                validation.PopParentExpression
            End Try
            Dim constructorBindingFlags As BindingFlags = (BindingFlags.Public Or BindingFlags.Instance)
            If validation.AllowInternalMembers(type) Then
                constructorBindingFlags = (constructorBindingFlags Or BindingFlags.NonPublic)
            End If
            If (type.IsValueType AndAlso (argumentExprs.Count = 0)) Then
                Return New RuleExpressionInfo(type)
            End If
            If type.IsAbstract Then
                [error] = New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.UnknownConstructor, New Object() { RuleDecompiler.DecompileType(type) }), &H137)
                [error].UserData.Item("ErrorObject") = newParent
                validation.Errors.Add([error])
                Return Nothing
            End If
            Dim info2 As RuleConstructorExpressionInfo = validation.ResolveConstructor(type, constructorBindingFlags, argumentExprs, [error])
            If (info2 Is Nothing) Then
                [error] = New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.UnknownConstructor, New Object() { RuleDecompiler.DecompileType(type) }), &H137)
                [error].UserData.Item("ErrorObject") = newParent
                validation.Errors.Add([error])
                Return Nothing
            End If
            Return info2
        End Function

    End Class
End Namespace

